#!/usr/bin/env python3

# Copyright (c) 2020-2021 Fpemud <fpemud@sina.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


from .._util import WinFile
from .._const import Arch, Version, Edition, Lang
from ._spec import Spec


class AnswerFile(WinFile):

    def __init__(self, ts):
        self._ts = ts

        # Local administrator accounts
        self.local_accounts = self._local_accounts

        self._first_logon_commands = collections.deque()
        self._setup_scripts = collections.deque()






        # Auto-logon options
        self.auto_logon = None

        # CmdKey account credentials
        self.cmd_key_account = None

        # Display resolution
        self.display_resolution = None

        # Windows product key
        self.product_key = None

        # Processor architecture
        self.processor_architecture = "amd64"

        # Time zone
        self.time_zone = "Pacific Standard Time"

        # First logon commands
        self.first_logon_commands = self._first_logon_commands

        # Setup scripts
        self.setup_scripts = self._setup_scripts

# LocalCredential class definition
class LocalCredential:
    def __init__(self, username, password, is_admin=False):
        self.username = username
        self.password = password
        self.is_admin = is_admin

# DomainOptions class definition
class DomainOptions:
    def __init__(self, domain, username, password):
        self.domain = domain
        self.username = username
        self.password = password

# AutoLogonOptions class definition
class AutoLogonOptions:
    def __init__(self, enabled, username, password):
        self.enabled = enabled
        self.username = username
        self.password = password

# DomainCredential class definition
class DomainCredential:
    def __init__(self, username, password):
        self.username = username
        self.password = password






    def get_filen_name(self):
        # unattend.xml can not be used in <windowsPE> stage and <offlineServicing> stage
        # autounattend.xml is to be used in all stages
        return "autounattend.xml"

    def get_content(self):
        spec = Spec(self._ts.arch)

        # assign values
        self.productId = self._ts.product_key

        buf = self._template
        buf = buf.replace("@@component_tag_postfix@@", " ".join([
                'processorArchitecture="%s"' % (spec.archDict[self._ts.arch]),
                'publicKeyToken="31bf3856ad364e35"',
                'language="neutral"',
                'versionScope="nonSxS"',
            ])
        )
        buf = buf.replace("@@pe_lang@@", spec.langDict[Lang.en_US])                  # use fixed PE language, no one reads it ;)
        buf = buf.replace("@@pe_input_lang@@", spec.localeCodeDict[Lang.en_US])      # same above
        buf = buf.replace("@@username@@", "A")
        buf = buf.replace("@@product_key@@", self.productId)

        return buf





if True:
    # based on the minimal config of https://schneegans.de/windows/unattend-generator
    _template = """
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
    <settings pass="windowsPE">
        <component name="Microsoft-Windows-International-Core-WinPE" @@component_tag_postfix@@>
            <UILanguage>@@pe_lang@@</UILanguage>
        </component>
        <component name="Microsoft-Windows-Setup" @@component_tag_postfix@@>
            <ImageInstall>
                <OSImage>
                    <InstallFrom>
                        <MetaData wcm:action="add">
                            <Key>/IMAGE/NAME</Key>
                            <Value>Windows 11 Pro</Value>
                        </MetaData>
                    </InstallFrom>
                </OSImage>
            </ImageInstall>
            <UserData>
                <ProductKey>
                    <Key>@@product_key@@</Key>
                    <WillShowUI>OnError</WillShowUI>
                </ProductKey>
                <AcceptEula>true</AcceptEula>
                <FullName>@@username@@</FullName>            <!-- fixme -->
            </UserData>
            <UseConfigurationSet>false</UseConfigurationSet>            <!-- fixme -->
        </component>
    </settings>
    <settings pass="oobeSystem">                                                                <!-- system Out-Of-Box-Experience -->
        <component name="Microsoft-Windows-International-Core" @@component_tag_postfix@@>
            <InputLocale>@@pe_input_lang@@</InputLocale>
            <SystemLocale>@@pe_lang@@</SystemLocale>
            <UILanguage>@@pe_lang@@</UILanguage>
            <UserLocale>@@pe_lang@@</UserLocale>
        </component>
        <component name="Microsoft-Windows-Shell-Setup" @@component_tag_postfix@@>
            <OOBE>
                <ProtectYourPC>3</ProtectYourPC>
                <HideEULAPage>true</HideEULAPage>
                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
                <HideOnlineAccountScreens>false</HideOnlineAccountScreens>
            </OOBE>
            <UserAccounts>
                <AdministratorPassword>
                    <Value></Value>
                    <PlainText>true</PlainText>
                </AdministratorPassword>
            </UserAccounts>
            <AutoLogon>
                <Username>Administrator</Username>
                <Enabled>true</Enabled>
                <LogonCount>1</LogonCount>
                <Password>
                    <Value></Value>
                    <PlainText>true</PlainText>
                </Password>
            </AutoLogon>
            <FirstLogonCommands>
                <SynchronousCommand wcm:action="add">
                    <Order>1</Order>
                    <CommandLine>powershell.exe -WindowStyle Normal -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\FirstLogon.ps1' -Raw | Invoke-Expression;"</CommandLine>
                </SynchronousCommand>
            </FirstLogonCommands>
        </component>
    </settings>
    <settings pass="specialize">
        <component name="Microsoft-Windows-Shell-Setup" @@component_tag_postfix@@>
            <ProductKey>@@product_key@@</ProductKey>		<!-- fixme, why again -->
        </component>
        <component name="Microsoft-Windows-Deployment" @@component_tag_postfix@@>
            <RunSynchronous>
                <RunSynchronousCommand wcm:action="add">
                    <Order>1</Order>
                    <Path>powershell.exe -WindowStyle Normal -NoProfile -Command "$xml = [xml]::new(); $xml.Load('C:\Windows\Panther\unattend.xml'); $sb = [scriptblock]::Create( $xml.unattend.Extensions.ExtractScript ); Invoke-Command -ScriptBlock $sb -ArgumentList $xml;"</Path>
                </RunSynchronousCommand>
            </RunSynchronous>
        </component>
    </settings>

    <Extensions xmlns="https://schneegans.de/windows/unattend-generator/">
        <ExtractScript>
param(
    [xml] $Document
);

foreach( $file in $Document.unattend.Extensions.File ) {
    $path = [System.Environment]::ExpandEnvironmentVariables( $file.GetAttribute( 'path' ) );
    mkdir -Path( $path | Split-Path -Parent ) -ErrorAction 'SilentlyContinue';
    $encoding = switch( [System.IO.Path]::GetExtension( $path ) ) {
        { $_ -in '.ps1', '.xml' } { [System.Text.Encoding]::UTF8; }
        { $_ -in '.reg', '.vbs', '.js' } { [System.Text.UnicodeEncoding]::new( $false, $true ); }
        default { [System.Text.Encoding]::Default; }
    };
    $bytes = $encoding.GetPreamble() + $encoding.GetBytes( $file.InnerText.Trim() );
    [System.IO.File]::WriteAllBytes( $path, $bytes );
}
        </ExtractScript>
        <File path="C:\Windows\Setup\Scripts\FirstLogon.ps1">
$scripts = @(
    {
        Set-ItemProperty -LiteralPath 'Registry::HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name 'AutoLogonCount' -Type 'DWord' -Force -Value 0;
    };
);

&amp; {
  [float] $complete = 0;
  [float] $increment = 100 / $scripts.Count;
  foreach( $script in $scripts ) {
    Write-Progress -Activity 'Running scripts to finalize your Windows installation. Do not close this window.' -PercentComplete $complete;
    '*** Will now execute command &#xAB;{0}&#xBB;.' -f $(
      $str = $script.ToString().Trim() -replace '\s+', ' ';
      $max = 100;
      if( $str.Length -le $max ) {
        $str;
      } else {
        $str.Substring( 0, $max - 1 ) + '&#x2026;';
      }
    );
    $start = [datetime]::Now;
    &amp; $script;
    '*** Finished executing command after {0:0} ms.' -f [datetime]::Now.Subtract( $start ).TotalMilliseconds;
    "`r`n" * 3;
    $complete += $increment;
  }
} *&gt;&amp;1 &gt;&gt; "C:\Windows\Setup\Scripts\FirstLogon.log";
        </File>
    </Extensions>
</unattend>
        """
